home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
ici
/
ici.cpi
/
compile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-27
|
9KB
|
421 lines
#include "parse.h"
#include "array.h"
#include "op.h"
#include "str.h"
STATIC object_t *
new_binop(op)
int op;
{
register object_t *o;
#ifndef BINOPFUNC
/*
* This is the normal code.
*/
o = objof(new_op(NULL, OP_BINOP, t_subtype(op)));
#else
o = objof(new_op(ici_op_binop, 0, t_subtype(op)));
#endif
if (o != NULL)
loose(o);
return o;
}
/*
* Compile the expression into the code array, for the reason given.
* Returns -1 on failure, 1 on success.
*/
int
compile_expr(a, e, why)
array_t *a;
expr_t *e;
int why;
{
#define NOTLV(why) ((why) == FOR_LVALUE ? FOR_VALUE : (why))
if (pushcheck(a, 1))
return -1;
if (t_type(e->e_what) == T_BINOP && e->e_arg[1] != NULL)
{
if (e->e_what == T_COMMA)
{
if (compile_expr(a, e->e_arg[0], FOR_EFFECT) < 0)
return -1;
if (compile_expr(a, e->e_arg[1], why) < 0)
return -1;
return 1;
}
if (e->e_what == T_QUESTION)
{
array_t *a1;
array_t *a2;
if (e->e_arg[1]->e_what != T_COLON)
{
error = "syntax error in \"? :\" use";
return -1;
}
if (compile_expr(a, e->e_arg[0], FOR_VALUE) < 0)
return -1;
if ((a1 = new_array()) == NULL)
return -1;
if (compile_expr(a1, e->e_arg[1]->e_arg[0], why) < 0)
return -1;
if ((a2 = new_array()) == NULL)
{
loose(a1);
return -1;
}
if
(
compile_expr(a2, e->e_arg[1]->e_arg[1], why) < 0
||
pushcheck(a, 3)
)
{
loose(a1);
loose(a2);
return -1;
}
*a->a_top++ = objof(a1 = (array_t *)atom(objof(a1), 1));
*a->a_top++ = objof(a2 = (array_t *)atom(objof(a2), 1));
*a->a_top++ = objof(&o_ifelse);
loose(a1);
loose(a2);
return 1;
}
if (e->e_what == T_LESSEQGRT)
{
if (compile_expr(a, e->e_arg[0], FOR_LVALUE) < 0)
return -1;
if (compile_expr(a, e->e_arg[1], FOR_LVALUE) < 0)
return -1;
if (pushcheck(a, 1))
return -1;
if ((*a->a_top = objof(new_op(NULL, OP_SWAP, why))) == NULL)
return -1;
loose(*a->a_top);
a->a_top++;
return 1;
}
if (e->e_what == T_EQ)
{
/*
* Simple assignment.
*/
if (compile_expr(a, e->e_arg[0], FOR_LVALUE) < 0)
return -1;
if (compile_expr(a, e->e_arg[1], FOR_VALUE) < 0)
return -1;
if (pushcheck(a, 1))
return -1;
if ((*a->a_top = objof(new_op(NULL, OP_ASSIGN, why))) == NULL)
return -1;
loose(*a->a_top);
a->a_top++;
return 1;
}
if (e->e_what >= T_EQ)
{
/*
* Assignment op.
*/
if (compile_expr(a, e->e_arg[0], FOR_LVALUE) < 0)
return -1;
if (pushcheck(a, 1))
return 1;
*a->a_top++ = objof(&o_dotkeep);
if (compile_expr(a, e->e_arg[1], FOR_VALUE) < 0)
return -1;
if (pushcheck(a, 2))
return 1;
if ((*a->a_top = new_binop(e->e_what)) == NULL)
return -1;
++a->a_top;
if ((*a->a_top = objof(new_op(NULL, OP_ASSIGN, why))) == NULL)
return -1;
loose(*a->a_top);
a->a_top++;
return 1;
}
if (why == FOR_LVALUE)
goto notlvalue;
if (e->e_what == T_ANDAND || e->e_what == T_BARBAR)
{
register array_t *a1;
if (compile_expr(a, e->e_arg[0], FOR_VALUE) < 0)
return -1;
if ((a1 = new_array()) == NULL)
return -1;
if
(
compile_expr(a1, e->e_arg[1], FOR_VALUE) < 0
||
pushcheck(a, 3)
)
{
loose(a1);
return -1;
}
*a->a_top++ = objof(a1 = (array_t *)atom(objof(a1), 1));
loose(a1);
*a->a_top++ = objof(e->e_what == T_ANDAND ? &o_andand : &o_barbar);
if (why == FOR_EFFECT)
*a->a_top++ = objof(&o_pop);
return 1;
}
/*
* Ordinary binary op.
*/
if (compile_expr(a, e->e_arg[0], why) < 0)
return -1;
if (compile_expr(a, e->e_arg[1], why) < 0)
return -1;
if (pushcheck(a, 1))
return -1;
if (why == FOR_EFFECT)
return 1;
if ((*a->a_top = new_binop(e->e_what)) == NULL)
return -1;
++a->a_top;
return 1;
}
else
{
/*
* Not a "binary opertor".
*/
if (pushcheck(a, 3)) /* Worst case below. */
return -1;
switch (e->e_what)
{
case T_NULL:
if (why != FOR_EFFECT)
*a->a_top++ = objof(&o_null);
break;
case T_DOLLAR:
{
array_t *a1;
if ((a1 = new_array()) == NULL)
return -1;
if
(
compile_expr(a1, e->e_arg[0], NOTLV(why)) < 0
||
(e->e_obj = ici_evaluate(objof(a1), NULL)) == NULL
)
{
loose(a1);
return -1;
}
loose(a1);
}
/* Fall through. */
case T_INT:
case T_FLOAT:
case T_CONST:
case T_STRING:
if (why != FOR_EFFECT)
{
if (isstring(e->e_obj))
*a->a_top++ = objof(&o_quote);
*a->a_top++ = e->e_obj;
}
break;
case T_NAME:
if (why == FOR_LVALUE)
*a->a_top++ = objof(&o_namelvalue);
if (why != FOR_EFFECT)
*a->a_top++ = e->e_obj;
return 1;
case T_PLUS:
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
break;
case T_PLUSPLUS:
case T_MINUSMINUS:
if (e->e_arg[0] == NULL)
{
/*
* Postfix.
*/
if (compile_expr(a, e->e_arg[1], FOR_LVALUE) < 0)
return -1;
if (why == FOR_EFFECT)
goto pluspluseffect;
if (pushcheck(a, 4))
return -1;
*a->a_top++ = objof(&o_dotrkeep);
*a->a_top++ = objof(o_one);
if ((*a->a_top = new_binop(e->e_what == T_PLUSPLUS ? T_PLUS : T_MINUS)) == NULL)
return -1;
++a->a_top;
if ((*a->a_top = objof(new_op(NULL, OP_ASSIGN, FOR_EFFECT))) == NULL)
return -1;
loose(*a->a_top);
a->a_top++;
}
else
{
/*
* Prefix, (or possibly postfix for effect).
*/
if (compile_expr(a, e->e_arg[0], FOR_LVALUE) < 0)
return -1;
pluspluseffect:
if (pushcheck(a, 4))
return -1;
*a->a_top++ = objof(&o_dotkeep);
*a->a_top++ = objof(o_one);
if ((*a->a_top = new_binop(e->e_what == T_PLUSPLUS ? T_PLUS : T_MINUS)) == NULL)
return -1;
++a->a_top;
if ((*a->a_top = objof(new_op(NULL, OP_ASSIGN, why))) == NULL)
return -1;
loose(*a->a_top);
a->a_top++;
return 1;
}
break;
case T_EXCLAM:
case T_TILDE:
case T_MINUS:
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
if (why == FOR_EFFECT)
break;
if (pushcheck(a, 1))
return -1;
if ((*a->a_top = objof(new_op(op_unary, 0, t_subtype(e->e_what)))) == NULL)
return -1;
loose(*a->a_top);
++a->a_top;
break;
case T_AT:
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
if (why == FOR_EFFECT)
break;
if (pushcheck(a, 1))
return -1;
if ((*a->a_top = objof(new_op(NULL, OP_AT, 0))) == NULL)
return -1;
loose(*a->a_top);
++a->a_top;
break;
case T_AND: /* Unary. */
if (compile_expr(a, e->e_arg[0], why == FOR_VALUE ? FOR_LVALUE : why) < 0)
return -1;
if (why == FOR_EFFECT)
break;
if (pushcheck(a, 1))
return -1;
*a->a_top++ = objof(&o_mkptr);
break;
case T_ASTERIX: /* Unary. */
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
if (why == FOR_EFFECT)
break;
if (pushcheck(a, 1))
return -1;
if (why == FOR_LVALUE)
{
*a->a_top++ = objof(&o_openptr);
return 1;
}
else
*a->a_top++ = objof(&o_fetch);
break;
case T_ONSQUARE: /* Array or pointer index. */
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
if (compile_expr(a, e->e_arg[1], NOTLV(why)) < 0)
return -1;
if (why == FOR_EFFECT)
break;
if (pushcheck(a, 1))
return -1;
if (why == FOR_LVALUE)
return 1;
*a->a_top++ = objof(&o_dot);
break;
case T_PTR:
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
if (why != FOR_EFFECT)
{
if (pushcheck(a, 1))
return -1;
*a->a_top++ = objof(&o_fetch);
}
goto dot2;
case T_DOT:
if (compile_expr(a, e->e_arg[0], NOTLV(why)) < 0)
return -1;
dot2:
if (compile_expr(a, e->e_arg[1], NOTLV(why)) < 0)
return -1;
if (why == FOR_EFFECT)
break;
if (why == FOR_LVALUE)
return 1;
if (pushcheck(a, 1))
return -1;
*a->a_top++ = objof(&o_dot);
break;
case T_ONROUND: /* Function call. */
{
int nargs;
expr_t *e1;
nargs = 0;
for (e1 = e->e_arg[1]; e1 != NULL; e1 = e1->e_arg[1])
{
if (compile_expr(a, e1->e_arg[0], FOR_VALUE) < 0)
return -1;
++nargs;
}
if (compile_expr(a, e->e_arg[0], FOR_VALUE) < 0)
return -1;
if (pushcheck(a, 2))
return -1;
if ((*a->a_top = objof(new_op(NULL, OP_CALL, nargs))) == NULL)
return -1;
loose(*a->a_top);
++a->a_top;
if (why == FOR_EFFECT)
*a->a_top++ = objof(&o_pop);
}
break;
}
}
if (why == FOR_LVALUE)
{
if (pushcheck(a, 1))
return -1;
*a->a_top++ = objof(&o_mklvalue);
}
return 1;
notlvalue:
error = "lvalue required";
return -1;
}